﻿using System;
using System.Collections;
using System.Linq;
using System.Text;
using ZedGraph;
using System.Drawing;

namespace finalProjectGUI
{
    class GuiZedGraph
    {
        static private Color[] colors = { Color.Fuchsia, Color.LimeGreen, Color.SlateBlue, Color.Goldenrod, Color.Gray, Color.Black, Color.Red, Color.Gray, Color.Green, Color.LightBlue, Color.MediumVioletRed, Color.Cyan, Color.Coral, Color.Chocolate, Color.Orange, Color.MidnightBlue, Color.Olive };
        static public void drawClusterGraph2(ZedGraphControl zg1, int clusterNum, ArrayList data)
        {
            drawClusterGraph2(zg1, clusterNum, data, null,"");
        }
        /// <summary>
        /// This method draws the detailed cluster graph which shows all files and distances
        /// from this cluster medoid
        /// </summary>
        /// <param name="zg1"></param>
        /// <param name="clusterNum"></param>
        /// <param name="data"></param>
        static public void drawClusterGraph2(ZedGraphControl zg1, int clusterNum,ArrayList data,String[] names,String medoidLabel)
        {
            // get a reference to the GraphPane

            GraphPane myPane = zg1.GraphPane;
            myPane.CurveList.Clear();
            // Set the Titles

            myPane.Title.Text = "Cluster " + clusterNum + " details";
            myPane.XAxis.Title.Text = "File Number (see legend)";
            if (medoidLabel != "")
                myPane.XAxis.Title.Text += "\n Medoid belongs to label: " + medoidLabel;
            else
                myPane.Title.Text = "Distances of all files from Cluster " + clusterNum + " medoid";
            myPane.YAxis.Title.Text = "Distance from medoid";
           
            //myPane.XAxis.MajorGrid.IsVisible = true;
            myPane.YAxis.MajorGrid.IsVisible = true;
            BarItem myBar;
            int clusterColorIndex = 0;
            int numberOfFiles = 0;
            foreach (double[] clusterDistances in data)
            {
                String name;
                if (names == null)
                    name = "Cluster " + (clusterColorIndex + 1);
                else
                    name = names[clusterColorIndex];

                myBar = myPane.AddBar(name, null, clusterDistances, colors[clusterColorIndex]);
                myBar.Bar.Fill = new Fill(colors[clusterColorIndex], Color.White, colors[clusterColorIndex]);
                clusterColorIndex++;
                numberOfFiles = clusterDistances.Length;
            }
            String[] labels = new String[numberOfFiles];
            for (int i = 0; i < numberOfFiles; i++)
            {
                labels[i] = " " + (i+1);
            }
            
            // Draw the X tics between the labels instead of 

            // at the labels

            myPane.XAxis.MajorTic.IsBetweenLabels = true;

            // Set the XAxis labels

            myPane.XAxis.Scale.TextLabels = labels;
            // Set the XAxis to Text type

            myPane.XAxis.Type = AxisType.Text;

            // Fill the Axis and Pane backgrounds

            myPane.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 166), 90F);
            myPane.Fill = new Fill(Color.FromArgb(230, 230, 250)); //myPane.Fill = new Fill(Color.FromArgb(250, 250, 255));
            myPane.BarSettings.Type = BarType.Stack;
            // Tell ZedGraph to refigure the

            // axes since the data have changed

            zg1.AxisChange();
        }


        

        static public void CreateClusteringResultsGraph(ZedGraphControl zg1,guiClusteringResults CR)
        {
            // get a reference to the GraphPane

            GraphPane myPane = zg1.GraphPane;
            myPane.CurveList.Clear();
            // Set the Titles

            myPane.Title.Text = "Clustering results";
            myPane.XAxis.Title.Text = "Label";
            myPane.YAxis.Title.Text = "Number of files in cluster";
            myPane.YAxis.MajorGrid.IsVisible = true;
            
            // Make up data points

            string[] labels = CR.getLables();

            
            BarItem myBar;
            for (int i = 0; i < labels.Length; i++)
            {
                myBar = myPane.AddBar(labels[i], null, CR.getPoints(labels[i]), colors[i]);
                myBar.Bar.Fill = new Fill(colors[i], Color.White, colors[i]);
            }
           

            // Draw the X tics between the labels instead of 

            // at the labels

            myPane.XAxis.MajorTic.IsBetweenLabels = true;

            // Set the XAxis labels

            myPane.XAxis.Scale.TextLabels = CR.getClusterLables();
            // Set the XAxis to Text type

            myPane.XAxis.Type = AxisType.Text;

            // Fill the Axis and Pane backgrounds

            myPane.Chart.Fill = new Fill(Color.White,Color.FromArgb(255, 255, 166), 90F);
            myPane.Fill = new Fill(Color.FromArgb(250, 250, 255));
            
            //myPane.BarSettings.Type = BarType.Stack; //Bars are on top of eachOther
            myPane.BarSettings.Type = BarType.Cluster;
            // Tell ZedGraph to refigure the

            // axes since the data have changed

            zg1.AxisChange();
            
        }
    }
    

    /*************************************************************************************************/
    /*************************************************************************************************/
    /*************************************************************************************************/

    class guiClusteringResults
    {
        private ArrayList labelCollection;
        private ArrayList clusterCollection;
        public guiClusteringResults()
        {
            labelCollection = new ArrayList();
            clusterCollection = new ArrayList();
        }
        
        /// <summary>
        /// This method is used for incrementing the correct label count at the counter (lables are on the coulmn cluster are the coulmns)
        /// </summary>
        /// <param name="clusterNum">Cluster number that the label is found at</param>
        /// <param name="label">The label that was found</param>
        public void inc(int clusterNum, String label)
        {
            //Get index of the label (this is the index to increment inside the column)
            int index = labelCollection.IndexOf(label);
            if (index == -1)
            {
                labelCollection.Add(label); // add the new label               
                index = labelCollection.Count - 1; //set the index
            }
            //Check if this cluster (coulmn) was allready added
            if (clusterCollection.Count < clusterNum + 1)
            {
                clusterCollection.Add(new ClusteringGraphColumn("Cluster "+ (clusterNum+1)));
            }
            //Increment the right coulmn at the right level
            ((ClusteringGraphColumn)clusterCollection[clusterNum]).inc(index); //increment the counter for the label at the correct cluster
          
        }

        /// <summary>
        /// This method is used to return the lables of the clustering
        /// </summary>
        /// <returns>This method returns an array of Strings containing the clustering results</returns>
        public String[] getLables()
        {
            String[] labels = new String[labelCollection.Count];
            for (int i = 0; i < labelCollection.Count; i++)
                labels[i] = (String)labelCollection[i];
            return labels;
        }

        /// <summary>
        /// This method is used to return the lables of the clusters
        /// </summary>
        /// <returns>This method returns an array of Strings containing the clustering results</returns>
        public String[] getClusterLables()
        {
            String[] labels = new String[clusterCollection.Count];
            for (int i = 0; i < clusterCollection.Count; i++)
                labels[i] = (String)((ClusteringGraphColumn)clusterCollection[i]).Label;
            return labels;
        }
        /// <summary>
        /// This method gets the set of points representing the cluster belongings of the labels
        /// </summary>
        /// <param name="clusterNum">Cluster num to get it's label belonging</param>
        /// <returns>This method returns an array of doubles</returns>
        public double[] getPoints(String label)
        {
            if (clusterCollection.Count == 0) return null; //if no clusters 
            if (!labelCollection.Contains(label)) return null; //if there is no such label
            
            double[] points = new double[clusterCollection.Count];
            levelArray(); //make sure that each array has the same amount of cells(cell is representing a cluster count);

            for (int i = 0; i < clusterCollection.Count; i++)
                points[i] = (double)(int)(((ClusteringGraphColumn)clusterCollection[i])[labelCollection.IndexOf(label)]);
            return points;
        }
        
        /// <summary>
        /// This method makes sure that all the label array have the same amount of numbers
        /// </summary>
        private void levelArray()
        {
            int max = 0;
            foreach (ClusteringGraphColumn cluster in clusterCollection)
            {
                if (cluster.Count > max) max = cluster.Count;
            }
            foreach (ClusteringGraphColumn cluster in clusterCollection)
            {
                cluster.level(max);
            }

        }

    }
    
    class ClusteringGraphColumn : ArrayList
    {
        private String label;
        public String Label
        {
            get { return label; }
            set { label = value; }
        }
        public ClusteringGraphColumn(String label)
        {
            this.label = label;
        }
        /// <summary>
        /// This method increments the count at the appropriate cluster
        /// </summary>
        /// <param name="clusterNum">number of cluster to increment</param>
        public void inc(int levelToInc)
        {
            while (this.Count - 1 < levelToInc) //if this level was not refrenced yet
            {
                this.Add(0);
            }

            this[levelToInc] = ((int)this[levelToInc] + 1); //increase count
        }

        /// <summary>
        /// This method adds levels to Column if neccery
        /// </summary>
        /// <param name="level">The wanted level for this coulumn</param>
        public void level(int level)
        {
            while (this.Count < level) //the array is not levled add zeros
            {
                this.Add(0);
            }
        }
    }

}
